Metadata-Version: 2.4
Name: aioffice
Version: 0.4.0
Summary: An AI-native, declarative document engine for creating and validating office artifacts.
Author: AiOffice Maintainers
Project-URL: Homepage, https://github.com/HuiTurn/aioffice
Project-URL: Repository, https://github.com/HuiTurn/aioffice
Project-URL: Issues, https://github.com/HuiTurn/aioffice/issues
Project-URL: Documentation, https://github.com/HuiTurn/aioffice#readme
Keywords: ai,office,docx,document,agent
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: defusedxml<1,>=0.7.1
Requires-Dist: pydantic<3,>=2.7
Provides-Extra: render
Requires-Dist: Pillow<13,>=10; extra == "render"
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == "dev"
Requires-Dist: pyright<2,>=1.1.400; extra == "dev"
Requires-Dist: ruff<1,>=0.15; extra == "dev"
Requires-Dist: twine<7,>=5; extra == "dev"

# AiOffice

[![PyPI version](https://img.shields.io/pypi/v/aioffice.svg)](https://pypi.org/project/aioffice/)
[![Python versions](https://img.shields.io/pypi/pyversions/aioffice.svg)](https://pypi.org/project/aioffice/)
[![Source code](https://img.shields.io/badge/source-GitHub-1f6feb.svg)](https://github.com/HuiTurn/aioffice)

AiOffice is an AI-native document engine for creating and editing DOCX files
through stable selectors, strict schemas, validated plans, and verifiable output.
Agents work with document semantics instead of Word object APIs or OOXML internals.

The current `0.4.0` release is an alpha milestone. It provides:

- lossless opening and conservative editing of existing DOCX packages;
- stable semantic node IDs and deterministic target resolution;
- eight professional recipes for common document tasks;
- 75+ typed operations with progressively disclosed JSON Schema;
- atomic `plan` / `commit` transactions with revision conflict detection;
- semantic, native-package, reopen, accessibility, privacy, and visual QA gates;
- a Python API, CLI, workspace model, and transport-neutral six-tool adapter.

The active document spec is the `0.2` draft exposed by
`aioffice.spec.models.SPEC_VERSION`. The public API can continue to evolve before
1.0.

## Why AiOffice

### Agent-safe targeting

`inspect()` and `locate()` return stable selectors such as `#status` and never
require an agent to construct native references. Ambiguous queries are reported as
`ambiguous`; AiOffice does not silently choose the first result.

### Transactional editing

Every edit can be planned before it is committed. Plans are bound to one artifact
revision, validated against strict operation models, and protected by a deterministic
hash.

### Verifiable DOCX output

For imported DOCX files, AiOffice preserves untouched package parts byte-for-byte
and reports whether every native change was declared and the result remains a valid
OPC package. Professional tasks can additionally reopen and render the result before
delivery.

## Install

```bash
pip install aioffice
```

AiOffice requires Python 3.11 or newer.

For raster page analysis and visual quality gates:

```bash
pip install "aioffice[render]"
```

Native PDF/PNG rendering also requires LibreOffice and Poppler on the host. See
[the native rendering contract](docs/native-rendering.md).

## Create a document

```python
from aioffice import DocumentBuilder

doc = (
    DocumentBuilder(title="Project Report", theme="business-clean")
    .heading("Project Report", id="report_title")
    .paragraph("The first delivery milestone is complete.", id="status")
    .bullet_list(
        ["Validated spec", "Generated DOCX", "Published HTML preview"]
    )
    .build()
)

validation = doc.validate()
assert validation.valid

doc.export("report.json")
doc.export("report.md")
doc.export("report.html")
doc.export("report.docx")
```

## Professional Agent workflow

For common editing tasks, use the recipe layer:

```python
import aioffice

doc = aioffice.open("report.docx")

# Discover structure and resolve one target without guessing.
outline = doc.inspect(view="outline")
assert outline["nodes"]

resolution = doc.locate(query="Draft", scope="all")
if resolution.status != "resolved" or resolution.selected is None:
    raise RuntimeError(resolution.diagnostic or "Target was not resolved.")

task = {
    "recipe": "text.replace-scoped",
    "target": {"selector": resolution.selected.selector},
    "parameters": {
        "search": "Draft",
        "replacement": "Approved",
    },
    "constraints": {
        "visual_review": "optional",
        "require_native_verification": True,
    },
    "acceptance": {
        "must_contain": ["Approved"],
        "must_not_contain": ["Draft"],
    },
}

# Planning does not mutate the source document.
plan = doc.plan_task(task)
if not plan.valid:
    raise RuntimeError([item.model_dump() for item in plan.diagnostics])

# Commit atomically, then require professional QA to pass.
result = doc.commit_task(plan)
if not result.success:
    raise RuntimeError(result.model_dump())

assert result.quality.passed
result.commit.artifact.export("updated.docx")
```

The workflow is:

```text
open
  -> inspect
  -> locate
  -> recipe_schema
  -> plan_task
  -> review predicted changes
  -> commit_task
  -> quality report
  -> export
```

### Inspection views

| View | Purpose |
| --- | --- |
| `outline` | Heading hierarchy, sections, tables, images, stable selectors |
| `context` | One target with bounded neighboring nodes |
| `styles` | Style inventory, usage, direct and effective formatting |
| `table` | Bounded grids, cell IDs, spans, edit constraints |
| `layout` | Section geometry, floating images, layout diagnostics |
| `agent` | Paginated generic node discovery |
| `summary` | Compact artifact metadata and counts |
| `debug` | Native troubleshooting; not for normal agent edits |

### Deterministic target resolution

```python
resolution = doc.locate(
    query="Revenue",
    kinds=["paragraph", "table_cell_paragraph"],
    scope="all",
)

if resolution.status == "ambiguous":
    for match in resolution.matches:
        print(match.occurrence, match.selector, match.context_before)
    # Retry with a stable selector or ordinal=...
elif resolution.status == "not_found":
    raise LookupError(resolution.diagnostic)
else:
    selector = resolution.selected.selector
```

`find()` remains available for intentionally collecting multiple nodes. Check the
number of matches before selecting one.

## Professional recipes

Discover the compact catalog first, then fetch only the schema you need:

```python
catalog = doc.recipe_catalog()
schema = doc.recipe_schema("document.polish")
```

Built-in recipes:

| Recipe | Purpose | Risk |
| --- | --- | --- |
| `text.replace-scoped` | Exact replacement with ambiguity control | low |
| `template.fill` | Fill declared placeholders and detect missing fields | low |
| `document.polish` | Normalize headings, body, tables, and pagination | medium |
| `styles.normalize` | Normalize typography while preserving content | low |
| `table.polish` | Improve table geometry, headers, margins, and banding | low |
| `heading.toc-ready` | Normalize outline levels and optionally insert TOC | low/medium |
| `brand.apply` | Apply a theme and professional typography | medium |
| `review.finalize` | Accept/reject revisions and remove comments | high |

Initial professional profiles:

- `business-professional-zh`
- `business-professional-en`

Example:

```python
plan = doc.plan_task(
    {
        "recipe": "document.polish",
        "profile": "business-professional-zh",
        "parameters": {
            "fix_pagination": True,
            "apply_theme": False,
        },
        "constraints": {
            "preserve_brand": True,
            "visual_review": "required",
            "allow_page_count_change": False,
        },
        "acceptance": {
            "max_page_count_change": 0,
        },
    }
)

result = doc.commit_task(plan)
assert result.success
```

High-risk plans expose `requires_approval=True`. Review their normalized operations
before committing:

```python
if plan.requires_approval:
    print(plan.plan.normalized_operations)
    result = doc.commit_task(plan, approve=True)
```

See [Professional agent editing](docs/agent-professional-editing.md).

## Quality gates

`commit_task()` returns the normal commit evidence and a `QualityReport`.

```python
for gate in result.quality.gates:
    print(gate.name, gate.status, gate.message)

assert result.quality.passed
```

The built-in gates cover:

1. operation commit status;
2. semantic document validation;
3. recipe and caller acceptance assertions;
4. native DOCX package verification;
5. exported-DOCX reopen validation;
6. accessibility checks for image alt text and heading-level jumps;
7. privacy review for identifying, custom, or sensitive metadata;
8. optional or required rendered-page analysis, including page-count constraints.

Visual rendering failures are warnings when `visual_review="optional"` and hard
failures when it is `"required"`.

## Raw operations

Use raw operations for bespoke edits not covered by a recipe. Resolve one target,
fetch one strict schema, plan, and commit:

```python
resolution = doc.locate(
    query="Draft",
    kinds=["paragraph", "heading"],
    scope="all",
)
if resolution.status != "resolved" or resolution.selected is None:
    raise RuntimeError(resolution.diagnostic or "Target was not resolved.")

schema = doc.operation_schema("text.replace")

plan = doc.plan(
    [
        {
            "op": "text.replace",
            "target": resolution.selected.selector,
            "search": "Draft",
            "replacement": "Approved",
        }
    ]
)
assert plan.valid

commit = doc.commit(plan)
assert commit.success
commit.artifact.export("updated.docx")
```

The full operation union is intentionally not required in an agent prompt:

```python
compact_catalog = doc.recommend_operations(
    "Replace the approval status",
    selector=resolution.selected.selector,
)
operation_schema = doc.operation_schema(compact_catalog[0]["name"])
```

Advanced code can import typed operations:

```python
from aioffice.ops.document import ReplaceText

plan = doc.plan(
    [
        ReplaceText(
            target="#status",
            search="Draft",
            replacement="Approved",
        )
    ]
)
```

`Document.apply()` remains available for compatibility and engine-level workflows,
but new agent integrations should use `plan_task()` / `commit_task()` or
`plan()` / `commit()`.

## Native DOCX fidelity

Opening a DOCX attaches its native package while projecting supported content into
the semantic document model:

```python
doc = aioffice.open("existing.docx", roundtrip="preserve_unknown")
assert doc.origin == "native"

snapshot = doc.verify_fidelity()
assert snapshot.byte_identical
```

After a raw commit:

```python
verification = commit.verification
assert verification is not None
assert verification.verified
assert verification.undeclared_changes == []
assert verification.opc_valid
```

After a professional task, the same evidence is available at
`result.commit.verification` and is included in the quality report.

AiOffice rewrites only affected native parts and proves untouched parts are
byte-identical. Unsupported XML remains opaque and is preserved rather than guessed
at or reconstructed.

Read:

- [Native round-trip contract](docs/native-roundtrip.md)
- [Native fidelity verification](docs/native-verification.md)
- [Structural editing contract](docs/structural-editing.md)
- [Native image contract](docs/native-images.md)
- [Native rendering contract](docs/native-rendering.md)

## Six-tool adapter

`aioffice.agent.tools` provides a transport-neutral surface suitable for function
calling or an MCP integration:

1. `inspect_document`
2. `locate_content`
3. `list_recipes`
4. `plan_professional_task`
5. `commit_professional_task`
6. `verify_professional_result`

```python
from aioffice.agent import professional_tool_catalog

tools = professional_tool_catalog()
assert len(tools) == 6
```

The adapter is available now. A packaged network MCP Server, its authentication
model, and artifact storage policy remain future integration work.

## Golden-case evaluation

Use representative documents to continuously measure target and operation selection:

```python
from aioffice.agent import evaluate_professional_case

evaluation = evaluate_professional_case(
    doc,
    {
        "id": "approve-status",
        "task": {
            "recipe": "text.replace-scoped",
            "target": {"selector": "#status"},
            "parameters": {
                "search": "Draft",
                "replacement": "Approved",
            },
            "constraints": {"visual_review": "off"},
        },
        "expected_operations": ["text.replace"],
        "expected_targets": ["#status"],
    },
)

assert evaluation.passed
```

The evaluator reports plan validity, target recall, operation recall, commit status,
and quality-gate status.

## CLI

### Professional workflow

```bash
aioffice inspect report.docx --view outline
aioffice recipes list
aioffice recipes schema document.polish

aioffice task-plan report.docx task.json -o task-plan.json
aioffice task-commit report.docx task-plan.json \
  -o updated.docx \
  --report quality.json
```

Add `--approve` to `task-commit` only after reviewing a high-risk plan.

### Raw operations

```bash
aioffice ops list
aioffice ops describe text.replace
aioffice ops schema text.replace

aioffice plan report.docx patch.json -o plan.json
aioffice commit report.docx plan.json -o updated.docx
```

Patch files accept an operation array or an envelope:

```json
{
  "operations": [
    {
      "op": "text.replace",
      "target": "#status",
      "search": "Draft",
      "replacement": "Approved"
    }
  ]
}
```

### Inspection, validation, rendering, and schemas

```bash
aioffice inspect report.docx --view styles
aioffice inspect report.docx --view table --selector "#metrics"
aioffice capabilities report.docx
aioffice validate report.docx

aioffice render report.docx --format pdf -o report.pdf
aioffice render-pages report.docx --analyze --output-directory evidence

aioffice schema --kind operations -o operations.schema.json
aioffice schema --kind agent-protocol -o agent-protocol.schema.json
aioffice verify original.docx updated.docx \
  --declared-affected /word/document.xml
```

### Workspace

```bash
aioffice workspace init project
aioffice workspace import existing.docx --root project
aioffice workspace list --root project
aioffice workspace inspect ARTIFACT_ID --root project
aioffice workspace apply ARTIFACT_ID patch.json --root project
aioffice workspace reconcile ARTIFACT_ID edited.docx --root project --commit
aioffice workspace export ARTIFACT_ID updated.docx --root project
```

## Supported scope

| Surface | Status |
| --- | --- |
| DOCX creation and semantic editing | supported |
| Existing DOCX lossless open and conservative native editing | supported |
| JSON and Markdown document input | supported |
| JSON, Markdown, semantic HTML, and DOCX output | supported |
| Native PDF/PNG rendering and visual evidence | supported with host tools |
| XLSX, PPTX, and PDF semantic editing | planned |
| Packaged network MCP Server | planned; six-tool adapter available |

Feature availability can depend on the current document and native package:

```python
summary = doc.capabilities()
preflight = doc.preflight("table.row.insert", selector="#metrics")
```

The operation registry is the source of truth. See the generated
[capability matrix](docs/capabilities.md) for the complete status vocabulary and
feature-level caveats.

## Documentation

- [Professional Agent editing](docs/agent-professional-editing.md)
- [Capability matrix](docs/capabilities.md)
- [Style and rendering contracts](docs/style-rendering.md)
- [Paragraph formatting surfaces](docs/paragraph-surfaces.md)
- [Table layout](docs/table-layout.md)
- [Header and footer editing](docs/header-footer.md)
- [Section layout](docs/section-layout.md)
- [Dynamic fields](docs/dynamic-fields.md)
- [Security policy](SECURITY.md)
- [Changelog](CHANGELOG.md)

## Development

```bash
python -m pip install -e ".[dev,render]"
python -m unittest discover -s tests -q
ruff check src tests
pyright
python -m build
python -m twine check dist/*
```

Capability documentation is generated from the registry:

```bash
aioffice capability-doc
aioffice capability-drift
```

Production releases use PyPI Trusted Publishing. The release tag must match the
version in `src/aioffice/_version.py`.

Compatibility is maintained within the active `0.4.x` line where practical. The
document spec and public model remain pre-1.0 and can still evolve.
